home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -in_the_mag- / banging_the_metal / peek+poke / peek+poke.asm < prev    next >
Assembly Source File  |  1999-04-03  |  24KB  |  1,027 lines

  1. * POKES.ASM - dangerous shell commands to examine and modify memory contents.
  2. * Written in HiSoft Devpac 3.14, ver 1.5, March 1997; requires WB 2 or above.
  3. * Copyright 1995-96 SNG, freely distributable; you use this at your own risk.
  4.  
  5. * Version 1.5 is a maintenance release for Aminet with minor source tweaks.
  6.  
  7. * Updates since version 1.3:
  8. *
  9. * Uses Tadek Knapik's AnyLongToString to write numbers in hex and binary.
  10. * Appends a new line character to the output of PEEK.
  11. * Allows BINARY as a synonym for BIN and H as a short form for HEX.
  12. * Supports addresses and values in hex or binary as well as decimal.
  13. * Closes DOS.LIBRARY even if READARGs fails.
  14. * Suppresses leading zeroes in hexadecimal and binary output.
  15. * Supports PEEK (but not POKE?) STRING argument.
  16. * Supports AT for indirect addressing, to save extra PEEK LONGs.
  17.  
  18. * To do:
  19. *
  20. * Support for output of SIGNED values?
  21. * Allow task=task-name argument to access task-relative data?
  22.  
  23. * Overview:
  24. *
  25. * These commands were written for three purposes:
  26.  
  27. * (1) To allow low-level access to hardware and memory, from the CLI.
  28. * (2) To prevent the need to write little bits of code for each POKE.
  29. * (3) To experiment with some non-trivial ReadArgs parameter parsing.
  30. * (0) To annoy people who believe that POKEs are a thing of the past.
  31.  
  32. * Features:
  33.  
  34. * Can POKE or PEEK a byte, word or long word at any 32 bit memory address.
  35. * Supports signed or unsigned decimal values, reduced MOD size if necessary. 
  36. * Addressing can be relative to the base of any library, device or resource,
  37. * or relative to CUSTOM (the base of the Amiga custom chips), CIAA or CIAB.
  38. * Absolutely no protection so you can POKE anything anywhere. Caveat POKEr!
  39.  
  40. * Typical uses: in general these are not endorsed by Amiga Technology, and
  41. * library, device and resource offsets can vary between software releases.
  42. * These examples show the flexible format of various acceptable parameters:
  43.  
  44. * POKE ciaa 0 2        - Turns the audio filter off
  45. * POKE CIAA 0 0        - Turns the audio filter on
  46. * PEEK L 4            - Returns the EXEC library base address
  47. * PEEK CUSTOM 18        - Controller 0 left paddle position
  48. * PEEK CUSTOM 19                 - Controller 0 right paddle position
  49. * PEEK Res potgo WORD 20    - Version number of POTGO.RESOURCE
  50. * peek word lib dos 22    - Revision number of DOS.LIBRARY
  51. * peek lib exec long 42    - Contents of EXEC cold-capture vector
  52. * POKE CUSTOM WORD 48 511    - Sends MIDI RESET to the serial port
  53. * POKE WORD dev="narrator" 48 90 - Sets speech rate to 90 words/minute
  54. * peek LONG lib "graphics" 50    - Address of current Copper List
  55. * POKE W DEV "narrator" 54 1     - Narrator attempts a female voice
  56. * peek lib="exec" 62 long    - Returns the top of Chip Memory
  57. * peek 62 word lib graphics    - Returns the current screen display mode
  58. * poke w Dev narrator 62 16    - Set -12 dB Narrator speech volume
  59. * PEEK W lib "graphics" 232    - Microseconds per scan line * 256
  60. * peek lib graphics.library 236    - ChipSet revision, e.g. OCS/ECS/AGA  
  61. * POKE CIAB 256 119        - Start motor of DF0, stop other drives
  62. * poke 256 129 ciab        - Stop all floppy disk drive motors
  63. * PEEK long library "exec" 276    - Returns base address of this task 
  64. * peek LIBRARY="exec" w 296    - Returns ATTN_FLAGS (CPU type)
  65. * POKE LIB "exec.library" 297 1    - Pretend this CPU is a 68010!
  66. * Peek LIB "exec" 530        - Returns the vertical blanking frequency
  67. * PEEK 531 lib exec        - Returns power supply frequency in Hertz
  68. * PEEK LONG Library "exec" 568    - Number of timer 'E clocks' per second
  69. * PEEK CIAB 2048        - Low byte of 24 bit scan-line counter
  70. * PEEK dev=parallel string long 10 - "parallel.device", or "pit.device" if
  71. *            MapDevice parallel 0 to pit 0 is active.
  72.  
  73. * See Mapping The Amiga, The Amiga Guru Book and the CBM Includes for lots
  74. * more interesting and dangerous offsets. The best and most hazardous ones
  75. * are secret. If you're not sure, PEEK first and POKE afterwards (perhaps)!
  76.  
  77. * Notes on parameter and result handling:
  78.  
  79. * You may specify the transfer size and device/resource/library/hardware
  80. * base in any order, so PEEK WORD CUSTOM 18 means the same as PEEK 18 WORD
  81. * CUSTOM or PEEK W 18 CUSTOM or PEEK CUSTOM WORD 18. The choice is yours.
  82.  
  83. * Unfortunately qualifiers (LIB, LIBRARY, RES, DEVICE etc) must appear just
  84. * before the name of the library, resource or device which you want to use,
  85. * so you need to say PEEK LIB exec 530 as PEEK exec LIB 530 will not work. 
  86.  
  87. * The Device option always selects unit zero, with 0 in the 'flags' field.
  88.  
  89. * Combinations of switches are additive, so PEEK LIB exec CUSTOM 2 reads
  90. * the byte at ExecBase + $DFF000 + 2, which is unlikely to be very useful.
  91.  
  92. * The AT parameter indicates indirect addressing. The long word at the
  93. * specified address is read and used as a pointer to the required data.
  94. * Absolutely no validity checks are performed.
  95.  
  96. * Numeric values may be specified in decimal, binary with a % prefix, or
  97. * hexadecimal if prefixed with $, 0X or 0x. Excessive values are reduced
  98. * modulo the transfer size, e.g. POKE 0 $123 stores $23 and POKE WORD 0
  99. * $123456 stores $3456. Thus conventional (decimal only) ReadArgs numeric
  100. * parsing cannot be used for value and address arguments, so the /N does
  101. * not appear in the argument template. Nonetheless, VALUE and ADDRESS
  102. * arguments are numeric.
  103.  
  104. * By default PEEK returns a decimal number, but it can be a string up to
  105. * 32 bytes long (stopping after 32 bytes or at the first null) returned
  106. * in quotes, if the STRING switch is supplied, a value in binary, or in
  107. * hexadecimal, indicated by the HEX or H switch and $ prefix before the
  108. * number for base 16. The BIN or BINARY switch sets base 2 and a % prefix. 
  109.  
  110. * The STRING parameter expects that the argument is the offset of a pointer
  111. * to the required string rather than the offset of the start of the string.
  112.  
  113. * Numeric parameters are 32 bit signed or unsigned decimal values. Results
  114. * are unsigned bytes or words, signed long words. The default data size is
  115. * BYTE - this is not a switch. Words and bytes are reduced modulo 65536 and
  116. * modulo 256 respectively. Device, Resource and library names are case-
  117. * sensitive and the .suffix is assumed if not explicitly presented. All
  118. * other keywords are case-insensitive. Quotes, verbose qualifiers and
  119. * equals signs are optional. PEEK returns an ASCII string followed by
  120. * a trailing space and a newline, or nothing if an error occurs. You
  121. * can  redirect this to  an environment variable and use its value later
  122. * in your shell script. For instance, this code checks the current CPU
  123. * and writes an appropriate message if it's a 68040 and 68060:
  124.  
  125. * PEEK lib=exec 297 >env:CPU
  126. * IF $CPU equ 127
  127. *   ECHO "68040 processor"
  128. * ELSE
  129. *   IF $CPU equ 255
  130. *     ECHO "68060 processor"
  131. *   ENDIF
  132. * ENDIF
  133.  
  134. * EVAL can be used with PEEK environment variables. For instance this
  135. * sequence finds the start address of any Commodore Kickstart ROM:
  136.  
  137. * PEEK LONG $FFFFEC >env:ROMsize
  138. * EVAL 65536*256-$ROMsize
  139.  
  140. * There is currently no check for uneven-addressed words or long words,
  141. * which cause an odd address guru on 68000/68010 systems but work fine
  142. * on later processors, including all the current 32 bit Amiga models.
  143.  
  144. * Attempts to access non-existent memory on a Zorro 3 Amiga cause a bus
  145. * error after a delay of a fraction of a second, unless remapped by MMU.
  146.  
  147. * Source organisation:
  148.  
  149. * No include files are needed as all necessary constants are in this file.
  150. * This stand-alone source file includes the code for PEEK as well as POKE.
  151. * Choose the one you want by setting PEEK equ 0 for POKE, PEEK=1 for PEEK.
  152.  
  153. PEEK    equ    1
  154.  
  155. MaxName    equ    64        Limit total length of name
  156.  
  157. * EXEC.LIBRARY jump table offsets
  158.  
  159. CloseLibrary equ    -414
  160. OpenDevice    equ    -444
  161. CloseDevice equ    -450
  162. OpenResource equ    -498
  163. OpenLibrary equ    -552    
  164.  
  165. * DOS.LIBRARY jump table offsets
  166.  
  167. ReadArgs    equ    -798
  168. FreeArgs    equ    -858
  169. VPrintf    equ    -954
  170.  
  171. * Offsets for ReadArgs results
  172.  
  173. WordSize    equ    0
  174. LongSize    equ    4
  175. LibName    equ    8
  176. DevName    equ    12
  177. ResName    equ    16
  178. Custom    equ    20
  179. CIAA    equ    24
  180. CIAB    equ    28
  181. AT    equ    32    Indirect address
  182.  
  183.     ifeq    PEEK
  184.  
  185. Address    equ    36
  186. Value    equ    40
  187.  
  188.            else
  189.  
  190. Hex    equ    36    Return hexadecimal with $ prefix
  191. Bin    equ    40    Return binary number with % prefix
  192. String    equ    44    Return quoted ASCII string
  193. Address    equ    48
  194.  
  195.     endc
  196.  
  197.     SECTION    INSTRUCTIONS,CODE
  198.  
  199. Start    move.l    4.w,a6
  200.     move.l    a6,ExecBase
  201.     moveq    #37,d0        Version 2.00 +
  202.     lea.l    DosName,a1
  203.     jsr    OpenLibrary(a6)
  204.  
  205.     move.l    d0,DosBase
  206.     beq    Fail
  207.     
  208.     move.l    d0,a6
  209.     move.l    #Template,d1
  210.     lea.l    ArgTable,a2
  211.     move.l    a2,d2
  212.     moveq    #0,d3        No explicit RDARGS yet
  213.     jsr    ReadArgs(a6)
  214.  
  215.     move.l    d0,d1
  216.     beq    LateFail        ** 1.4 ** 
  217.  
  218.     jsr    FreeArgs(a6)
  219.  
  220.     move.l    ExecBase,a6
  221.     move.l    Address(a2),a0    Pointer to string
  222.     jsr    AnyStrToLong
  223.     tst.l    d1
  224.     beq    LateFail
  225.     
  226.     move.l    d0,a3        Where to PEEK or POKE (or offset)
  227.  
  228. * Find library base if necessary
  229.  
  230.     move.l    LibName(a2),d0
  231.     beq.s    NotLibrary
  232.  
  233.     lea.l    LibSuffix,a0
  234.     bsr    NameCheck
  235.     
  236.     moveq    #0,d0        Any library version
  237.     jsr    OpenLibrary(a6)    Call EXEC
  238.  
  239.     move.l    d0,CloseBase
  240.     bne.s    AddBase
  241.     
  242.     bra    LateFail
  243.     
  244. * Find device base if necessary
  245.  
  246. NotLibrary    move.l    DevName(a2),d0
  247.     beq.s    NotDevice    
  248.  
  249.     lea.l    DevSuffix,a0
  250.     bsr    NameCheck
  251.     
  252.     move.l    a1,a0        Pointer to device name
  253.     move.l    #ioRequest,a1
  254.     moveq    #0,d0        Unit number
  255.     moveq    #0,d1        No special flags
  256.     jsr    OpenDevice(a6)
  257.     
  258.     tst.l    d0
  259.     bne    LateFail
  260.  
  261.     move.l    #ioRequest,a1
  262.     add.l    20(a1),a3        Add base of device structure
  263.     move.l    a1,CloseBase    Store what thou shalt restore
  264.     bra.s    NotResource
  265.  
  266. * Track down a resource, if necessary
  267.  
  268. NotDevice    move.l    ResName(a2),d0
  269.     beq.s    NotResource
  270.  
  271.     lea.l    ResSuffix,a0
  272.     bsr    NameCheck
  273.  
  274.     jsr    OpenResource(a6)    Call EXEC
  275.  
  276.     tst.l    d0        No need to store this one
  277.     beq    LateFail
  278.     
  279. AddBase    add.l    d0,a3        Add base to supplied address
  280.  
  281. * If users mix and match switches, this code just totals ALL the offsets!
  282.  
  283. NotResource tst.l    Custom(a2)
  284.     beq.s    NotCustom
  285.     
  286.     add.l    #$DFF000,a3
  287.     
  288. NotCustom    tst.l    CIAA(a2)
  289.     beq.s    NotCIAA
  290.     
  291.     add.l    #$BFE001,a3
  292.     
  293. NotCIAA    tst.l    CIAB(a2)
  294.     beq.s    NotCIAB
  295.     
  296.     add.l    #$BFD000,a3
  297.         
  298. NotCIAB    tst.l    AT(a2)
  299.     beq.s    NotAT
  300.  
  301.     move.l    (a3),a3        Use indirect address
  302. NotAT    
  303.     ifeq    PEEK
  304.     
  305.       move.l    Value(a2),a0    Where to PEEK what to POKE
  306.       jsr    AnyStrToLong
  307.       tst.l    d1
  308.       beq.s    LateFail
  309.     
  310.     else
  311.     
  312.       moveq    #0,d0        Clear top bytes of result
  313.  
  314.     endc
  315.     
  316.     tst.l    WordSize(a2)
  317.     bne.s    PokeWord
  318.     
  319.     tst.l    LongSize(a2)
  320.     bne.s    PokeLong
  321.  
  322.     ifeq    PEEK        
  323.     
  324.       move.b    d0,(a3)
  325.       bra.s    Done
  326.  
  327. PokeLong      move.l    d0,(a3)        Must be word aligned if < 68020!
  328.       bra.s    Done
  329.     
  330. PokeWord      move.w    d0,(a3)        Beware odd alignment on old CPUs
  331.  
  332.     else
  333.     
  334.       move.b    (a3),d0
  335.       bra.s    Return
  336.  
  337. PokeLong      move.l    (a3),d0        Must be even boundary if < 68020!
  338.       bra.s    Return
  339.     
  340. PokeWord      move.w    (a3),d0        Odd alignment crashes old CPUs
  341.  
  342. * Send the result in D0 back to the shell with VPRINTF
  343.  
  344. Return      lea.l    Buffer,a0
  345.  
  346.       tst.l    String(a2)
  347.       beq.s    NotString
  348.      
  349.       move.l    d0,a1
  350.       moveq    #32-1,d1        Maximum to write to buffer
  351.       move.b   #'"',(a0)+
  352.       
  353. CopyString      move.b    (a1)+,(a0)+
  354.       dbeq     d1,CopyString
  355.       bne.s    Terminate    
  356.       subq.l   #1,a0                 Remove trailing null if any
  357. Terminate      move.b   #'"',(a0)+
  358.       clr.b    (a0)        Terminate with extreme prejudice
  359.       bra.s    Report
  360.             
  361.       
  362. NotString      move.l    #LTS_DECIMAL,d1
  363.       tst.l    Hex(a2)
  364.       beq.s    NotHex
  365.       
  366.       move.l    #LTS_HEX,d1
  367.       move.b    #'$',(a0)+
  368.       bra.s    Cooked
  369.  
  370. NotHex      tst.l    Bin(a2)
  371.       beq.s    Cooked
  372.       
  373.       move.l    #LTS_BINARY,d1
  374.       move.b    #'%',(a0)+
  375. *      bra.s    Cooked
  376.       
  377. Cooked      jsr    AnyLongToStr
  378.       tst.l    d0
  379.       beq.s    LateFail
  380.       
  381. Report      move.l    #StrFormat,d1
  382.              move.l    #Result,d2
  383.              move.l    #Buffer,Result
  384.              move.l    DosBase,a6
  385.              jsr    VPrintf(a6)
  386.  
  387.     endc
  388.  
  389. * Close whatever library/device/resource we have opened before returning
  390.                 
  391. Done    move.l    ExecBase,a6
  392.     move.l    CloseBase,a1
  393.     move.l    LibName(a2),d0
  394.     beq.s    LibFree
  395.     
  396.     jsr    CloseLibrary(a6)
  397.  
  398. LibFree    move.l    DevName(a2),d0
  399.     beq.s    CloseDOS
  400.     
  401.     jsr    CloseDevice(a6)
  402.     
  403. CloseDOS    move.l    DosBase,a1
  404.     jsr    CloseLibrary(a6)
  405.     
  406.     moveq    #0,d0
  407.     rts
  408.  
  409.  
  410. * Direct exit from NameCheck if string is too long for our buffer
  411.  
  412. LaterFail    addq.l    #4,a7        Return to prior caller
  413.  
  414. * Exit used when the program fails after opening DOS.LIBRARY
  415.     
  416. LateFail    move.l    DosBase,a1
  417.     move.l    ExecBase,a6
  418.     jsr    CloseLibrary(a6)
  419.     
  420. Fail    moveq    #30,d0
  421.     rts
  422.  
  423.  
  424. * Ensure name string at D0 includes a dot, or add the suffix
  425. * at A0. Return A1 pointing to the checked string. Uses A4,D4.
  426.  
  427. NameCheck    moveq    #MaxName-1,d1    -1 for DBEQ loops later
  428.     lea.l    OpenName,a4
  429.     move.l    d0,a1
  430.  
  431. Scan    move.b    (a1)+,d4
  432.     cmp.b    #'.',d4
  433.     beq.s    GotDot
  434.  
  435.     move.b    d4,(a4)+
  436.     dbeq    d1,Scan               Continue till null or D1=-1
  437.  
  438.     bne.s    LaterFail
  439.  
  440.     subq.l    #1,a4        Step back over dot    
  441.     addq.w    #1,d1        Adjust limit count
  442.  
  443. Append    move.b    (a0)+,(a4)+
  444.     dbeq    d1,Append
  445.  
  446.     bne.s    LaterFail        We never reached the null!
  447.  
  448.     lea.l    OpenName,a1    Point at start of our copy
  449.     rts
  450.     
  451. GotDot    move.l    d0,a1        Use the literal string
  452.     rts
  453.  
  454.     SECTION    TADEK,CODE
  455.  
  456. **********************************************************************
  457. *
  458. *    AnyStrToLong - convert ASCII string to 32-bit value
  459. *
  460. * Input:  a0 - null terminated string
  461. * Output: d0 - the value (was $FFFFFFFF if error - removed by SNG)
  462. *         d1 - success (boolean)
  463. *
  464. *    As string you can pass decimal (no prefix), binary (prefix '%')
  465. * or hex (prefixes '$' or '0x'). Check d1 for success or failure (fails
  466. * when non-specific characters are found, or if null string).
  467. *    In hex/bin mode, when you pass too many characters, only last
  468. * 8/32 are used. In dec mode, maximal value is 4.294.967.295
  469. * ($FFFFFFFF). Decimal values may be negative (prefix '-'), then the
  470. * range is from -2.147.483.647 to 2.147.483.648 (otherwise the result
  471. * is not reliable).
  472. *
  473. *    Alters only scratch registers (d0, d1, a0, a1). Uses 16 bytes
  474. * of stack (decimal mode only).
  475. *
  476. *
  477. *    © 1996 by Tadek Knapik (tadek@student.uci.agh.edu.pl).
  478. *         Public Domain. E-mail appreciated :-)
  479. *
  480. **********************************************************************
  481.  
  482.  
  483.  
  484. AnyStrToLong:
  485. ;;    cmpi.b    #0,(a0)        ;null string?
  486.     tst.b    (a0)        ;; SNG - faster
  487.     beq.s    AnyStrToLongError
  488.  
  489.     moveq    #0,d0        ;negative flag in decimal mode
  490.  
  491.     cmpi.b    #'-',(a0)        ;negative?
  492.     beq    DecStrToLong0
  493.  
  494.     cmpi.b    #'%',(a0)        ;binary?
  495.     beq.s    BinStrToLong0    ;yes!
  496.  
  497.     cmpi.b    #'$',(a0)        ;hex
  498.     beq.s    HexStrToLong0    ;yes!
  499.  
  500.     cmpi.b    #'0',(a0)        ;hex (0x)
  501.     bne    DecStrToLong    ;no!
  502.  
  503.     movea.l    a0,a1        ;string pointer
  504.     adda.l    #1,a1
  505.     cmpi.b    #'X',(a1)        ;; Capital check, SNG
  506.     beq.s    Prefix0X
  507.     
  508.     cmpi.b    #'x',(a1)        ;'x'?
  509.     bne.s    DecStrToLong    ;
  510.  
  511. Prefix0X    addq.l    #1,a0        ;;omit '0' (Q not A)
  512.  
  513. ;;    bra.s    HexStrToLong
  514.  
  515.  
  516. ;--------------------
  517.  
  518. ;convert hex to long.
  519.  
  520. HexStrToLong0:
  521.     addq.l    #1,a0        ;;next byte (omit '$/x/X')
  522.  
  523. HexStrToLong:
  524.     moveq    #0,d0
  525.     moveq    #0,d1
  526.  
  527. HexNextNybble:
  528.     tst.b    (a0)        ;;the end?
  529.     beq.s    AnyStrToLongEnd    ;yes
  530.  
  531. ;next character
  532.  
  533.     lsl.l    #4,d0        ;prepare next 4 bits
  534. ;;    moveq    #0,d1        ;clr = redundant, SNG
  535.     move.b    (a0)+,d1        ;next cipher
  536.  
  537.     cmpi.b    #'0',d1        ;lower than 0?
  538.     blt.s    AnyStrToLongError
  539.  
  540.     cmpi.b    #'f',d1        ;higher than f?
  541.     bgt.s    AnyStrToLongError
  542.  
  543.     subi.b    #'0',d1        ;ASCII '0'
  544.     bmi.s    AnyStrToLongError
  545.  
  546. ;now we have 0-9. Or not..
  547.  
  548.     cmpi.b    #9,d1        ;more than '9'?
  549.     ble.s    HexReady        ;no, we're done
  550.  
  551.     subq.b    #7,d1        ;;try this
  552.  
  553. ;If A-F, we have 10-15, unless <, >, @ etc., or a-f
  554.  
  555.     cmpi.b    #10,d1        ;less than 'A'?
  556.     blt.s    AnyStrToLongError    ;yes, jump @ Error
  557.  
  558.     cmpi.b    #15,d1        ;more than 'F'
  559.     ble.s    HexReady        ;OK
  560.  
  561. ;so, probably a-f
  562.  
  563.     subi.b    #32,d1        ;case change?
  564.  
  565.     cmpi.b    #10,d1        ;less?
  566.     blt.s    AnyStrToLongError    ;yes, probably XYZ
  567.  
  568.     cmpi.b    #15,d1        ;more than 'f'
  569.     ble.s    HexReady        ;no, OK
  570.     bra.s    AnyStrToLongError    ;error, probably xyz
  571.  
  572. ;in d1 we have value in range 0-15
  573.  
  574. HexReady:
  575.     or.b    d1,d0        ;set those bits
  576.     bra.s    HexNextNybble    ;next one, please
  577.  
  578.  
  579. AnyStrToLongError:
  580. ;;    moveq    #-1,d0        ;;if -1 in d0, then 
  581.     moveq    #0,d1        ;d1 is boolean failure
  582.     rts
  583.  
  584. AnyStrToLongEnd:
  585.     moveq    #1,d1        
  586.     rts
  587.  
  588. ;--------------------
  589.  
  590. ;convert binary to long.
  591.  
  592. BinStrToLong0:
  593.     addq.l    #1,a0        ;;next byte
  594. BinStrToLong:
  595.     tst.b    (a0)        ;;nothing?
  596.     beq.s    AnyStrToLongError
  597.  
  598.     moveq    #0,d0
  599.     moveq    #0,d1
  600.  
  601. BinNextBit:
  602. ;;    cmpi.b    #0,(a0)        ;coô jeszcze
  603.     tst.b    (a0)        ;;faster 
  604.     beq    AnyStrToLongEnd
  605.  
  606. ;what do we have here..
  607.  
  608.     lsl.l    #1,d0        ;prepare next bit
  609.  
  610.     moveq    #0,d1
  611.     move.b    (a0)+,d1
  612.  
  613.     subi.b    #'0',d1        
  614.     bmi.s    AnyStrToLongError
  615.  
  616.     cmpi.b    #1,d1        ;more than 1?
  617.     bgt.s    AnyStrToLongError
  618.  
  619. ;now we have 0 or 1 in d1.
  620.  
  621.     or.b    d1,d0        ;to set or not to set
  622.     bra.s    BinNextBit
  623.  
  624. ;--------------------
  625.  
  626.  
  627. ;Convert decimal ASCII to 32 bit long.
  628. ;Maximum - 4.294.967.295 ($FFFFFFFF)
  629. ;If you pass in [x*4.294.967.295+y], it will probably return [y].
  630.  
  631.  
  632. DecStrToLong0:
  633.     addq.l    #1,a0        ;;next byte (omit '-')
  634.     moveq    #1,d0
  635.  
  636. DecStrToLong:
  637.     tst.b    (a0)        ;;nic?
  638.     beq.s    AnyStrToLongError
  639.     movem.l    d2-d5,-(sp)
  640.     move.l    d0,d5        ;negative flag
  641.  
  642.     moveq    #0,d1        ;clr
  643.     moveq    #0,d0        ;the value
  644.     movea.l    a0,a1        ;string
  645.     addq.l    #1,a1        ;;cause I add immediately
  646.  
  647. ;length of the string without last null character
  648.  
  649. DecStrLengthLoop:
  650.     addq.l    #1,d1
  651.     tst.b    (a1)+
  652.     bne.s    DecStrLengthLoop    
  653.  
  654. ;now in d1 we have the weight  of the first cipher plus 1
  655.  
  656. DecNextCipherLoop:
  657.     subq.l    #1,d1        ;sub 1
  658.  
  659.     tst.l    d1        ;if null, this is the last one
  660.     beq.s    DecLastCipher
  661.     move.l    d1,d2
  662.  
  663.     moveq    #0,d3
  664.     move.b    (a0)+,d3        ;the cipher
  665.  
  666.     subi.b    #'0',d3        
  667.     bmi.s    DecStrToLongError    
  668.  
  669.     cmpi.b    #9,d3        
  670.     bgt.s    DecStrToLongError
  671.  
  672.  
  673. DecMultipleLoop:
  674.     move.l    d3,d4        ;copy it
  675.  
  676.     lsl.l    #3,d3        ;*8
  677.     lsl.l    #1,d4        ;*2
  678.     add.l    d4,d3        ;x*2+x*8=x*(2+8)=x*10
  679.  
  680.     subq.l    #1,d2
  681.     bne.s    DecMultipleLoop
  682.  
  683.     add.l    d3,d0        
  684.     bra.s    DecNextCipherLoop
  685.  
  686.  
  687. DecLastCipher:
  688.     moveq    #0,d3
  689.     move.b    (a0)+,d3
  690.  
  691.     subi.b    #'0',d3    
  692.     bmi.s    DecStrToLongError
  693.  
  694.     cmpi.b    #9,d3        
  695.     bgt.s    DecStrToLongError
  696.  
  697.     add.l    d3,d0
  698.  
  699. DecStrToLongEnd:
  700.     tst.l    d5        ;was it negative?
  701.     beq.s    DecStrToLongPositiveEnd    
  702.     neg.l    d0        ;negate it
  703.  
  704. DecStrToLongPositiveEnd:
  705.     movem.l    (sp)+,d2-d5
  706.     bra    AnyStrToLongEnd
  707.  
  708. DecStrToLongError:
  709.     movem.l    (sp)+,d2-d5
  710.     bra    AnyStrToLongError
  711.  
  712.  
  713.     ifne    PEEK
  714.     
  715. **********************************************************************
  716. *
  717. *    AnyLongToStr - Convert 32-bit value to ASCII
  718. *
  719. * Input:  d0 - the value to convert
  720. *         d1 - flags
  721. *         a0 - pointer to a buffer 
  722. * Output: d0 - number of characters written (or null for error)
  723. *         a0 - address of the terminating null
  724. *
  725. *
  726. *    Flags are:
  727. *   LTS_DECIMAL   - normal decimal conversion
  728. *   LTS_SIGN_LONG - decimal signed mode (longword)
  729. *   LTS_SIGN_WORD - signed (word)
  730. *   LTS_SIGN_BYTE - signed (byte)
  731. *   LTS_BINARY    - convert to binary
  732. *   LTS_HEX_UPPER - convert to hex (A-F)
  733. *   LTS_HEX_LOWER - convert to hex (a-f)
  734. *
  735. *
  736. *    You should pass a buffer with at least 11/12 (decimal/negative
  737. * decimal), 9 (hex) or 33 (binary) bytes of space.
  738. *    If flags = #1, checks the 31 bit and if it is high, assumes
  739. * the  value is lower than 0.
  740. *    This string is null-terminated. Address of the terminating
  741. * null is returned in a0. The null is included in number of chars
  742. * written.
  743. *
  744. *    When you specify decimal non-signed mode, then even if
  745. * bit 31 is set you'll get value in range 0 to 4.294.967.295. In
  746. * signed mode you'll get values in range from -2.147.483.647 to
  747. * 2.147.483.648 (negative when bit 31/15/7 is set, depending on the
  748. * choosen mode). Minus sign is written, if needed (and added to chars
  749. * counter returned in d0).
  750. *
  751. *    No prefix is written in hex/bin mode!!! If you need it, write
  752. * it yourself. That's how you can choose between '$'/'0x' :-)
  753. *
  754. *    Alters only scratch registers (d0, d1, a0, a1). Uses 12 bytes
  755. * of stack.
  756. *
  757. *
  758. *    © 1996 by Tadek Knapik (tadek@student.uci.agh.edu.pl).
  759. *         Public Domain. E-mail appreciated :-)
  760. *
  761. **********************************************************************
  762.  
  763.  
  764. LTS_DECIMAL    equ    0
  765. LTS_BINARY        equ    2
  766. LTS_HEX_UPPER    equ    4
  767. LTS_HEX_LOWER    equ    8
  768. LTS_SIGN_LONG    equ    16
  769. LTS_SIGN_WORD    equ    32
  770. LTS_SIGN_BYTE    equ    64
  771. LTS_NEGATIVE    equ    LTS_SIGN_LONG
  772. LTS_HEX        equ    LTS_HEX_UPPER
  773.  
  774. AnyLongToStr:
  775.     movem.l    d2-d4,-(sp)
  776.     moveq    #0,d2        ;the counter
  777.  
  778.     cmpi.l    #LTS_DECIMAL,d1
  779.     beq.s    LTSDecConvert
  780.  
  781.     cmpi.l    #LTS_SIGN_LONG,d1
  782.     beq.s    LTSMinDecConvert
  783.  
  784.     cmpi.l    #LTS_SIGN_WORD,d1
  785.     beq.s    LTSMinWDecConvert
  786.  
  787.     cmpi.l    #LTS_SIGN_BYTE,d1
  788.     beq.s    LTSMinBDecConvert
  789.  
  790.     cmpi.l    #LTS_BINARY,d1
  791.     beq    LTSBinConvert
  792.  
  793.     move.l    #'A',d2        ;ASCII base uppercased
  794.  
  795.     cmpi.l    #LTS_HEX_UPPER,d1
  796.     beq    LTSHexConvert
  797.  
  798.     move.l    #'a',d2        ;ASCII base lowercased
  799.  
  800.     cmpi.l    #LTS_HEX_LOWER,d1
  801.     beq    LTSHexConvert
  802.  
  803. LTSError:
  804.     movem.l    (sp)+,d2-d4
  805.     moveq    #0,d1
  806.     moveq    #0,d0
  807.     rts
  808.  
  809. ;--------------------
  810.  
  811. LTSMinBDecConvert:
  812.     ext.w    d0        ;extend to word
  813. LTSMinWDecConvert
  814.     ext.l    d0        ;extend to longword
  815.  
  816. LTSMinDecConvert:
  817.     btst    #31,d0
  818.     beq.s    LTSDecConvert
  819.     move.b    #'-',(a0)+        ;the minus sign
  820.     addq.l    #1,d2
  821.     neg.l    d0        ;so I need plus now
  822.  
  823. LTSDecConvert:
  824.     moveq    #0,d1        ;zeroes flag
  825.     move.l    #1000000000,d4    ;32-bit max power of 10
  826.  
  827. LTSDecAgain:
  828.     cmp.l    d4,d0
  829.     bcc.s    LTSDecMatch
  830.  
  831.     tst.l    d1        ;write zeroes?
  832.     beq.s    LTSDecNextPass    ;not yet
  833.  
  834.     move.b    #'0',(a0)+        ;write it
  835.     addq.l    #1,d2        ;one character more
  836.     bra.s    LTSDecNextPass
  837.  
  838. LTSDecMatch:
  839.     moveq    #1,d1        ;means write zeros from now
  840.     moveq    #0,d3        ;clear temporary
  841.  
  842. LTSDecLoop:
  843.     addq.l    #1,d3
  844.  
  845.     sub.l    d4,d0
  846.     bpl.s    LTSDecLoop        ;branch if not less than 0
  847.  
  848.     add.l    d4,d0        ;did it too many times
  849.     subq.l    #1,d3        ;as well
  850.  
  851.     addi.l    #'0',d3        ;ASCII 0
  852.     move.b    d3,(a0)+
  853.     addq.l    #1,d2        ;the counter
  854.  
  855. LTSDecNextPass:
  856.     bsr.s    LTSDecDivideByTen
  857.     tst.l    d4
  858.     beq.s    LTSError
  859.  
  860.     cmpi.l    #1,d4
  861.     bne.s    LTSDecAgain
  862.  
  863. ;less than 10 in d0..
  864.  
  865.     addi.l    #'0',d0
  866.     move.b    d0,(a0)+
  867.     addq.l    #1,d2
  868.  
  869. LTSDecOver:
  870.     move.b    #0,(a0)
  871.     suba.l    #1,a0
  872.     addq.l    #1,d2        ;null is a character, too
  873.     move.l    d2,d0
  874.     movem.l    (sp)+,d2-d4
  875.     rts
  876.  
  877.  
  878. LTSDecDivideByTen:
  879.  
  880. ;
  881. ;if your proggy is to be run on 020+ only!
  882. ;
  883. ;    mulu.l    #10,d4
  884. ;    rts
  885.  
  886. ;now 68000 part. Thanks for Simon N Goodwin for this routine!
  887.  
  888.     moveq    #0,d3        ;temporary register
  889.     swap    d4        ;higher 16 bits
  890.     move.w    d4,d3    
  891.     divu    #10,d3        ;divide higher 16 bits
  892.     swap    d3        ;store in high word of d3
  893.     move.w    d3,d4        ;safe?
  894.     swap    d4        
  895.     divu    #10,d4                ;divide lower 16 bits
  896.     move.w    d4,d3    
  897.     exg    d3,d4
  898.     rts
  899.  
  900.  
  901. ;--------------------
  902.  
  903. ; Peephole optimisations and leading zero suppression by SNG
  904.  
  905. LTSHexConvert:
  906.     tst.l    d0        ;;Zero is special
  907.     bne.s    LTSHexSet
  908.     
  909. LTSzero    move.b    #'0',(a0)+
  910.     bra.s    LTSdone
  911.  
  912. LTSHexSet:    moveq    #8-1,d4        ;8 characters
  913.  
  914. LTSHexLoop:
  915.     rol.l    #4,d0        ;prepare next nybble
  916.  
  917.     moveq    #%1111,d1        ;; mask quick load
  918.     and.l    d0,d1        ;the nybble
  919.     beq.s    LTSHexTry
  920.     
  921.     bset    #31,d4        ;;Flag zero found
  922.          
  923. LTSHexTry    tst.l    d4        ;; Any zeroes yet?
  924.     bpl.s    LTSHexNxt
  925.     
  926.     moveq    #'0',d3        ;ASCII base (for 0-9)
  927.  
  928.     cmpi.l    #9,d1        ;normal or a-f
  929.     ble.s    LTSHexDec
  930.  
  931.     move.l    d2,d3        ;new base (A-F or a-f)
  932.     subi.l    #$A,d1        ;new value :-)
  933.  
  934. LTSHexDec:
  935.     add.l    d1,d3        ;add soup base, cover it and
  936.     move.b    d3,(a0)+        ;wait for 3 minutes :-)
  937.  
  938. LTSHexNxt:    dbra    d4,LTSHexLoop
  939.  
  940. LTSdone:    clr.b    (a0)        ;terminate
  941.     suba.l    #1,a0
  942.     movem.l    (sp)+,d2-d4    ;give it back..
  943.     moveq    #9,d0        ;no way for 8 :-)
  944.     rts
  945.  
  946. ;--------------------
  947.  
  948.  
  949. LTSBinConvert:
  950.     moveq    #32-1,d4        ;;DBRA 32 characters
  951.  
  952.     tst.l    d0
  953.     beq.s    LTSzero
  954.     
  955. LTSBinLoop:
  956.     rol.l    #1,d0        ;one bit
  957.  
  958.     moveq    #1,d1        ;;spare
  959.     and.l    d0,d1        ;;the bit
  960.     beq.s    LTSBinSup
  961.     
  962.     bset    #31,d4        ;;Sign
  963.     
  964. LTSBinSup    tst.l    d4
  965.     bpl.s    LTSBinNxt
  966.     
  967.  
  968. LTSBinOut    add.b    #'0',d1
  969.     move.b    d1,(a0)+        
  970.  
  971. LTSBinNxt    dbra    d4,LTSBinLoop    ;;do it again
  972.  
  973.     bra.s    LTSdone
  974.  
  975. ;;    clr.b    (a0)        ;terminate
  976. ;;    subq.l    #1,a0
  977. ;;    movem.l    (sp)+,d2-d4    ;give it back..
  978. ;;    moveq    #33,d0        ;am I sure of that?
  979. ;;    rts
  980.  
  981.     endc
  982.     
  983. **********************************************************************
  984.  
  985.     SECTION    STRINGS,DATA
  986.  
  987. Version    dc.b    '$VER: POKES 37.6 (28/3/97)',0
  988. DosName    dc.b    'dos'
  989. LibSuffix    dc.b    '.library',0
  990. DevSuffix    dc.b    '.device',0
  991. ResSuffix    dc.b    '.resource',0
  992.  
  993. Template    dc.b    'W=WORD/S,L=LONG/S,'
  994. Template2    dc.b    'LIB=LIBRARY/K,DEV=DEVICE/K,RES=RESOURCE/K,'
  995. Template3    dc.b    'C=CUSTOM/S,CIAA/S,CIAB/S,AT/S,'
  996.  
  997.     
  998.     ifeq    PEEK
  999.     
  1000. Template4      dc.b    'ADDRESS/A,VALUE/A',0
  1001.  
  1002.     else
  1003.     
  1004. Template5      dc.b    'H=HEX/S,BIN=BINARY/S,STRING/S,ADDRESS/A',0
  1005. StrFormat      dc.b    '%s ',10,0
  1006.  
  1007.     endc
  1008.     
  1009.  
  1010.     SECTION    VARIABLES,BSS
  1011.     
  1012. ExecBase    ds.l    1
  1013. DosBase    ds.l    1
  1014. CloseBase    ds.l    1        Points at the thing to be closed
  1015. ArgTable    ds.l    Address/4+2
  1016. ioRequest    ds.l    32        128 bytes should be enough?
  1017. OpenName    ds.b    MaxName        Overflows here if necessary
  1018.  
  1019.     ifne    PEEK
  1020.  
  1021. Buffer    ds.b    36        Not re-entrant    
  1022. Result    ds.l    1        Pointer to buffer
  1023.  
  1024.     endc
  1025.  
  1026.     end
  1027.